#include "GY_DialCircular.h"
#include <math.h>
#include <QtMath>
#include <QDebug>
#include "Graphics/GY_GraphicsReflection.h"

GY_DialCircular::GY_DialCircular(const QString &guid, QGraphicsItem *parent) : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    this->setCenterPointF(m_PropertyInfoMap["Position"].propertyValue.toPointF());
    m_pTransFormGroup = new GY_TransformGroup(QString("%1_Group").arg(guid),this);
    m_ChildrensMap.insert(m_pTransFormGroup->getGuid(),m_pTransFormGroup);
    this->addToGroup(m_pTransFormGroup);
    updateDraw();
    setContainerEditPointF();
}

GY_DialCircular::~GY_DialCircular()
{

}

void GY_DialCircular::setContainerEditPointF()
{
    QMap<QVariant,QPointF> editPoints = {
        {"RotationPoint",m_PropertyInfoMap["RotationPoint"].propertyValue.toPointF()}
    };
    this->setEditPointF(editPoints);
}

GY_Object *GY_DialCircular::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
//        return nullptr;
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = m_pTransFormGroup->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
//        if(childrens[i]->copyItem() == nullptr) {
//            qDebug()<<childrens[i]->getGuid()<<"isEmpty";
//            continue;
//        }
        ((GY_ContainerTransform*)pObj)->addItem(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

bool GY_DialCircular::addItem(GY_Object *pItem)
{
    m_pTransFormGroup->addItem((GY_Object*)pItem);
    //添加item之后重新添加组，捕获编辑点更精确
    this->addToGroup(m_pTransFormGroup);
    updateDraw();
    return true;
}

bool GY_DialCircular::removItem(const QString &guid)
{
    return m_pTransFormGroup->removItem(guid);
}

bool GY_DialCircular::removItem(const GY_Object *pItem)
{
    bool remove = m_pTransFormGroup->removItem((GY_Object*)pItem);
    this->GY_ContainerTransform::removItem((GY_Object*)pItem);
    updateDraw();
    return remove;
}

void GY_DialCircular::initializationPropertyInfo()
{
    //隐藏
    GY_PropertyInfo isVisiblePropertyInfo(this);
    isVisiblePropertyInfo.propertyName="IsVisible";
    isVisiblePropertyInfo.propertyValue=true;
    isVisiblePropertyInfo.updateType = Update|OrdinaryAttributes;
    isVisiblePropertyInfo.propertyType = BoolPropertyType;
    isVisiblePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_DialCircular::updateIsVisible;
    m_PropertyInfoMap.insert(isVisiblePropertyInfo.propertyName,isVisiblePropertyInfo);
    m_PropertyInfoMap[isVisiblePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_DialCircular::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Position";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_DialCircular::updatePosition;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo valuePropertyInfo(this);
    valuePropertyInfo.propertyName="Value";
    valuePropertyInfo.propertyValue=0;
    valuePropertyInfo.updateType = Update|OrdinaryAttributes;
    valuePropertyInfo.propertyType = QrealPropertyType;
    valuePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_DialCircular::updateValue;
    m_PropertyInfoMap.insert(valuePropertyInfo.propertyName,valuePropertyInfo);
    m_PropertyInfoMap[valuePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo startAnglePropertyInfo(this);
    startAnglePropertyInfo.propertyName="StartAngle";
    startAnglePropertyInfo.propertyValue=0;
    startAnglePropertyInfo.updateType = Update|OrdinaryAttributes;
    startAnglePropertyInfo.propertyType = QrealPropertyType;
    startAnglePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_DialCircular::updateStartAngle;
    m_PropertyInfoMap.insert(startAnglePropertyInfo.propertyName,startAnglePropertyInfo);
    m_PropertyInfoMap[startAnglePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo valuePerRevolutionPropertyInfo(this);
    valuePerRevolutionPropertyInfo.propertyName="ValuePerRevolution";
    valuePerRevolutionPropertyInfo.propertyValue=2;
    valuePerRevolutionPropertyInfo.updateType = Update|OrdinaryAttributes;
    valuePerRevolutionPropertyInfo.propertyType = QrealPropertyType;
    valuePerRevolutionPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_DialCircular::updateValuePerRevolution;
    m_PropertyInfoMap.insert(valuePerRevolutionPropertyInfo.propertyName,valuePerRevolutionPropertyInfo);
    m_PropertyInfoMap[valuePerRevolutionPropertyInfo.propertyName].setConnect();

    //旋转点
    GY_PropertyInfo RotationPointPropertyInfo(this);
    RotationPointPropertyInfo.propertyName="RotationPoint";
    RotationPointPropertyInfo.propertyValue=QPointF(50,0);
    RotationPointPropertyInfo.updateType = NotUpdate;
    RotationPointPropertyInfo.propertyType = PointPropertyType;
    RotationPointPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_DialCircular::updateRotationPoint;
    m_PropertyInfoMap.insert(RotationPointPropertyInfo.propertyName,RotationPointPropertyInfo);
    m_PropertyInfoMap[RotationPointPropertyInfo.propertyName].setConnect();

}

void GY_DialCircular::updateDraw()
{
    qreal value = m_PropertyInfoMap["Value"].propertyValue.toReal();
    qreal startAngle = m_PropertyInfoMap["StartAngle"].propertyValue.toReal();
    qreal valuePerRevolution = m_PropertyInfoMap["ValuePerRevolution"].propertyValue.toReal();
    qreal remainder = fmod(value,valuePerRevolution);
    m_pTransFormGroup->setRotationCenter(QPointF(0,0));
    m_pTransFormGroup->setContainerRotation(startAngle+(remainder/valuePerRevolution)*360);
}

bool GY_DialCircular::updatePosition(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //setpos设置为父级坐标
    QPointF point = value.toPointF();
    if(this->parentItem()) {
        point = this->mapToParent(this->mapFromScene(value.toPointF()));
    }
    this->setPos(point);
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    updateDraw();
    return true;
}

bool GY_DialCircular::updateValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}

bool GY_DialCircular::updateStartAngle(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    if(value.toReal() > 360) {
        m_PropertyInfoMap[name].propertyValue=fmod(value.toReal(),360);
    }else if(value.toReal() < -360) {
        m_PropertyInfoMap[name].propertyValue=fmod(value.toReal(),-360);
    }else {
        m_PropertyInfoMap[name].propertyValue=value.toReal();
    }
    updateDraw();
    QPointF  Point1=precalculatedPosition(QPointF(0,0),50,m_PropertyInfoMap[name].propertyValue.toReal());
    m_PropertyInfoMap["RotationPoint"].propertyValue=Point1;
    this->setEditPointF("RotationPoint",Point1);
    return true;
}

bool GY_DialCircular::updateValuePerRevolution(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}

bool GY_DialCircular::updateRotationPoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF point=this->mapFromScene(value.toPointF());
    //基于圆心的偏移坐标
    qreal pointAngle=precalculatedAngle(QPointF(0,0),point);
    if(pointAngle > 180) {
        m_PropertyInfoMap["StartAngle"].propertyValue=-(360-pointAngle);
    }else {
        m_PropertyInfoMap["StartAngle"].propertyValue=pointAngle;
    }
    QPointF  Point1=precalculatedPosition(QPointF(0,0),50,pointAngle);
    updateDraw();
    m_PropertyInfoMap[name].propertyValue=Point1;
    this->setEditPointF(name,Point1);
    return true;
}

bool GY_DialCircular::updateIsVisible(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    this->setVisible(value.toBool());
    return true;
}

qreal GY_DialCircular::precalculatedAngle(const QPointF &centerPoint, const QPointF &calculatePoint)
{
    //基于圆心的偏移坐标
    QPointF diffPoint=calculatePoint-centerPoint;
    qreal pointAngle=qRadiansToDegrees(qAtan2(diffPoint.y(),diffPoint.x()));
    if(diffPoint.y()<0)
    {
        pointAngle+=360;
    }
    return pointAngle;
}

QPointF GY_DialCircular::precalculatedPosition(const QPointF &centerPoint, const double radius, const double angele)
{
    qreal radian=qDegreesToRadians(angele); //弧度
    QPointF resultPoint;
    resultPoint.setX(cos(radian)*radius);
    resultPoint.setY(sin(radian)*radius);
    resultPoint+=centerPoint;
    return resultPoint;
}

